package cn.wgx.module.mind.websocket.config.interceptor;

import cn.wgx.module.mind.websocket.config.WebSocketStompConfig;
import cn.wgx.module.mind.websocket.entity.WSPrincipal;
import cn.wgx.module.mind.websocket.util.OnlineUserTool;
import cn.wgx.module.mind.websocket.util.SWLockUtil;
import cn.wgx.module.mind.websocket.util.UserForbidden;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptor;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.security.oauth2.provider.OAuth2Authentication;

import java.security.Principal;
import java.util.Map;

/**
 *  stomp 事件
 */

public class UserInterceptor implements ChannelInterceptor {

    private Logger logger = LoggerFactory.getLogger(UserInterceptor.class);

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
        Object uri = sessionAttributes.get("uri");
        if(uri != null){
            return message;
        }
        StompCommand command = accessor.getCommand();
        if (StompCommand.CONNECT.equals(command)) {
            //首次连接准备工作
            return connection(message, accessor);
        }else if(StompCommand.SEND.equals(command)){
            return send(message, accessor);
        }else if(StompCommand.SUBSCRIBE.equals(command)){
            return subscribe(message, accessor);
        }else if(StompCommand.UNSUBSCRIBE.equals(command)){
            return unsubscribe(message, accessor);
        }else if (StompCommand.DISCONNECT.equals(command)) {
            //断开连接时
            return disConnection(message, channel, accessor);
        }
        //3.不是首次连接，已经登陆成功
        return message;
    }



    private Message<?> connection(Message<?> message, StompHeaderAccessor accessor) {
        //todo 验证用户身份
        //将系统用户转换为ws用户对象
        Principal user = accessor.getUser();
        if(user instanceof OAuth2Authentication){
            OAuth2Authentication oa = (OAuth2Authentication)user;
            Object principal = oa.getUserAuthentication().getPrincipal();
            //初始化用户信息
            WSPrincipal ws = new WSPrincipal();
            BeanUtils.copyProperties(principal, ws);
            accessor.setUser(ws);
            accessor.getSessionAttributes().put("principal", ws);
            if (logger.isDebugEnabled()) {
                logger.debug("用户:" + ws.getNickname() + "加入连接.");
            }
            return message;
        }
        return null;
    }


    private Message<?> subscribe(Message<?> message, StompHeaderAccessor accessor) {
        WSPrincipal user = (WSPrincipal) accessor.getUser();
        //accessor.getHeader();
        if(null != user){
            String roomId = getRoomIdByAccessor(accessor, true);
            //设置加入房间号
            user.setRoomId(roomId);

            //判断此用户是否已被禁言
            user.setForbidden(UserForbidden.isForbidden(roomId, user.getName()));

            //判断是管理员,可以禁言别人
            if(user.getName().equals("admin")){
                user.setAdmin(true);
            }
//            if(OnlineUserTool.isJoin(destination.get(0), user)){
//                //todo 拒绝登录如何返回错误结果？
//                return message;
//            }
            String simpDestination = message.getHeaders().get("simpDestination").toString();
            if(!simpDestination.startsWith(WebSocketStompConfig.USER_DESTINATION)){
                OnlineUserTool.addUser(roomId, user);
            }
//            Object payload = message.getPayload();
            return message;
        }
        return message;
    }


    private Message<?> send(Message<?> message, StompHeaderAccessor accessor) {
        return message;
    }


    private Message<?> unsubscribe(Message<?> message, StompHeaderAccessor accessor) {
        // 取消订阅 扫尾工作
        WSPrincipal user = (WSPrincipal)accessor.getUser();

        if(user != null){
            OnlineUserTool.delUser(user.getRoomId(), user);
            SWLockUtil.unlockProByUser(user.getName(), user.getRoomId());
        }

        return message;
    }

    public Message<?> disConnection(Message<?> message, MessageChannel channel, StompHeaderAccessor accessor) {
        // 断开连接 扫尾工作
        WSPrincipal user = (WSPrincipal)accessor.getUser();
        if(user != null){
//            OnlineUserTool.delUser(user.getRoomId(), user);
            SWLockUtil.unlockAllByUser(user.getName());
        }
        return message;
    }

    private String getRoomIdByAccessor(StompHeaderAccessor accessor, boolean isSub){
        String str = isSub?".":"/";
        String roomId = accessor.getNativeHeader("destination").get(0);
        return roomId.substring(roomId.lastIndexOf(str) + 1);
    }


}
